// File:    expr.cpp
// Author:  Brian Vanderburg II
// Purpose: Expression object
//------------------------------------------------------------------------------

// Includes
#include <new>
#include <memory>

#include "COMMON/expr/expr.h"
#include "COMMON/expr/parser.h"
#include "COMMON/expr/node.h"
#include "COMMON/expr/error.h"

namespace ExprEval
{

Expression::Expression() :
    m_vlist (0),
    m_flist (0),
    m_expr(0)
{}



Expression::~Expression()
{
    delete m_expr;
}



void
Expression::SetValueList (
    ValueList* vlist)
{
    m_vlist = vlist;
}



ValueList*
Expression::GetValueList() const
{
    return m_vlist;
}



void
Expression::SetFunctionList (
    FunctionList* flist)
{
    m_flist = flist;
}



FunctionList*
Expression::GetFunctionList() const
{
    return m_flist;
}



bool
Expression::Parse (
    const std::string& exstr,
    const bool stop_when_numeric_limits_reached)
{
    m_errors.setStopWhenNumericLimitsReached (stop_when_numeric_limits_reached);
    m_expr_str = exstr;
    // Clear the expression if needed
    if(m_expr)
        Clear();

    // Create parser
    std::auto_ptr<Parser> p(new Parser(this));

    bool good_parse=true;

    // Parse the expression
    m_expr = p->Parse (exstr, good_parse);
    return good_parse;
}



void
Expression::Clear()
{
    delete m_expr;
    m_expr = 0;
}



double
Expression::Evaluate()
{
    if(m_expr)
    {
        const double result = m_expr->Evaluate (m_errors);
        m_errors.check_error(m_expr_str);
        return result;
    }
    else
    {
        //throw(EmptyExpressionException());
        SHOW_FATAL_ERROR("empty expression");
        return 0.;
    }
}



std::pair<double, double>
Expression::Evaluate (
    const std::string& var_symbol)
{
    if(m_expr)
    {
        const std::pair<double, double> result = m_expr->Evaluate (var_symbol, m_errors);
        m_errors.check_error(m_expr_str);
        return result;
    }
    else
    {
        //throw(EmptyExpressionException());
        SHOW_FATAL_ERROR("empty expression");
        return std::make_pair (0., 0.);
    }
}



std::pair<double, double>
Expression::Evaluate (
    const std::string& var_symbol_1,
    const std::string& var_symbol_2)
{
    if(m_expr)
    {
        const std::pair<double, double> result = m_expr->Evaluate (var_symbol_1, var_symbol_2, m_errors);
        m_errors.check_error(m_expr_str);
        return result;
    }
    else
    {
        //throw(EmptyExpressionException());
        SHOW_FATAL_ERROR("empty expression");
        return std::make_pair (0., 0.);
    }
}



const std::string&
Expression::getExprString() const
{
    return m_expr_str;
}



std::string
Expression::get_renamed_expression (
    const std::string& var_map_name) const
{
    return m_expr->get_renamed_expression (var_map_name);
}

}
